package com.atguigu.tingshu.common.thread;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author GQS @Date 2024/11/5/23:38 @Description
 * 自定义线程池
 */
@Configuration
public class GuiguThreadPoolConfig {
  @Bean
  public ThreadPoolExecutor threadPoolExecutor(){
    /**
     * 线程池的核心参数:
     * 1.核心线程数: 一般小于或者等于cpu核心数
     * 2.最大线程数:
     *      a.逻辑密集型(计算,数据处理)=cpu的核心数
     *      b.IO(网络请求 本地文件的IO)密集型=cpu的核心数*2+(1)
     * 3.非核心线程的闲置时间+单位(回收的时间)--->只针对非核心线程生效
     * 4.阻塞队列: 任务分配的优先级: 核心线程>阻塞队列>非核心线程的>拒绝策略
     *      a.有界: 有容量限制的--->会触发非核心线程创建+拒绝策略--->数组
     *      b.无界: 没有容量限制的--->不会触发非核心线程创建+拒绝策略--->链表
     * 5.拒绝策略:
     *      a.AbortPolicy: 不执行任务,分配任务的线程获取到异常
     *      b.CallerRunsPolicy: 任务执行了, 谁分配的任务谁自己执行--->影响分配任务的线程的效率
     *      c.DiscardPolicy:  不执行任务,任务直接丢掉
     *      d.DiscardOldestPolicy: 将等待时间最久的任务丢弃,新任务交给线程池执行
     *      e.自定义: 为RejectedExecutionHandler做一个实现类即可
     */
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            12,//核心线程数
            24,//最大线程数
            10,//非核心线程的闲置时间: 注意-->非核心线程数=最大线程数-核心线程数
            TimeUnit.SECONDS,//非核心线程的闲置时间单位
            new ArrayBlockingQueue<>(10000),//阻塞队列
            Executors.defaultThreadFactory(),//线程工厂对象
            new ThreadPoolExecutor.AbortPolicy());//拒绝策略
    /**
     * 线程池的工作流程(膨胀流程):
     * 1.实例化完成的一个线程池对象,,在这个线程池中的状态为:
     *      核心线程: 0个 非核心线程: 0个 阻塞队列: 0个
     * 2.在给线程池分配12个任务后,线程池中的状态为:
     *      核心线程: 12个 非核心线程: 0个 阻塞队列: 0个
     * 3.同时给线程池10000个任务,线程池中的状态为:
     *      核心线程: 12个 非核心线程: 0个 阻塞队列: 10000个
     * 4.同时给线程池12个任务,线程池中的状态为:
     *      核心线程: 12个 非核心线程: 12个 阻塞队列: 10000个
     * 5.同时给线程池N>0个任务,触发拒绝策略
     */
    return threadPoolExecutor;
  }

  /**
   * 注意事项:
   *  1.线程池不允许任务为空
   *  2.不论是核心线程还是非核心线程,优先执行触发创建自己的任务
   *  3.调用了线程池的shutdown方法,不再创建线程和接受新任务,但是工作中的线程会执行完自己的任务,再关闭线程池(推荐)
   *  4.调用了贤臣吃的shutdownNow方法,直接关闭线程池,不理会任务是否都执行完了(风险高,不推荐!)
   *  5.线程池的最大容量:
   *      a.肯定不是Integer.MAX_VALUE
   *      b.COUNT_BITS = Integer.SIZE - 3 = 29
   *          COUNT_MASK = 1 << 29 - 1 = 2`29-1  设置值: Integer.MAX_VALUE = 2`31 -1
   *          COUNT_MASK =29个1      &      Integer.MAX_VALUE=31个1
   *          最大值=COUNT_MASK
   *     c.结论: COUNT_MASK = 2`29-1个线程
   *     d.为什么少头3位?
   *          1.线程的id(编号从0开始到2`29-1结束)
   *          2.每个线程的id都由32位二进制记录,低29位用于记录线程的编号
   *          3.高三位省略的目的是记录线程的: 状态!
   *              101---(-1)--RUNNING
   *              000---(0)--SHUTDOWN
   *              001---(1)--STOP
   *              010---(2)--TIDYING
   *              011---(3)--TERMINATED
   */
}
